package com.example.lt.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.lt.constant.MessageConstant;
import com.example.lt.constant.MinioPicPathConstant;
import com.example.lt.constant.PicPathConstant;
import com.example.lt.exception.AdminOperateException;
import com.example.lt.exception.MinioOperateException;
import com.example.lt.mapper.CollectMapper;
import com.example.lt.mapper.CommentMapper;
import com.example.lt.mapper.SongMapper;
import com.example.lt.pojo.entity.Collect;
import com.example.lt.pojo.entity.Comment;
import com.example.lt.pojo.entity.Song;
import com.example.lt.pojo.vo.SongVO;
import com.example.lt.result.Result;
import com.example.lt.service.CommentService;
import com.example.lt.service.MinioService;
import com.example.lt.service.SongService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author 小涛Tao
 * @Date: 2024/06/02/19:47
 * version 1.0 注释：
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class SongServiceImpl extends ServiceImpl<SongMapper, Song> implements SongService {

    private final SongMapper songMapper;

    private final MinioService minioService;

    private final CommentMapper commentMapper;

    private final CollectMapper collectMapper;

    /**
     * 添加新歌曲
     * @param song
     * @return
     */
    public Result addSong(Song song, MultipartFile lrcFile, MultipartFile songFile) {
        String originalFilename = songFile.getOriginalFilename(); // 获取前端传来的歌曲文件名
        song.setPic(PicPathConstant.DEFAULT_SONG_PIC); // 设置歌曲默认图片
        song.setUrl(PicPathConstant.SONG_URL_PATH + originalFilename); // 设置歌曲音频的访问路径

        // 设置歌曲的歌词
        if (lrcFile != null && (song.getLyric().equals("[00:00:00]暂无歌词"))){
            byte[] fileContent = new byte[0];
            try {
                fileContent = lrcFile.getBytes();
                String content = new String(fileContent, "GB2312");
                song.setLyric(content);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        int flag = songMapper.insert(song); // 添加歌曲
        // 把歌曲音频上传到minio中
        String s = minioService.uploadFile(MinioPicPathConstant.SONG_PATH, originalFilename, songFile);
        if (s.equals("File uploaded successfully.") && flag > 0) {
            return Result.success(MessageConstant.SONG_ADD_SUCCESS);
        } else {
            throw new MinioOperateException(MessageConstant.SONG_ADD_FAIL);
        }

    }

    /**
     * 管理端更新歌曲的音频
     * @param urlFile
     * @param id
     * @return
     */
    @Transactional
    public Result updateSongUrl(MultipartFile urlFile, int id) {
        String originalFilename = urlFile.getOriginalFilename();
        String newUrl = PicPathConstant.SONG_URL_PATH + originalFilename; // 新的歌曲音频访问路径

        boolean flag = lambdaUpdate().eq(Song::getId, id).set(Song::getUrl, newUrl).update(); // 修改数据库中的歌曲音频访问路径

        String s = minioService.uploadFile(MinioPicPathConstant.SONG_PATH, originalFilename, urlFile); // 更新minio中的音频
        if (s.equals("File uploaded successfully.") && flag) {
            return Result.success(MessageConstant.SONG_URL_ALTER_SUCCESS, newUrl);
        } else {
            throw new MinioOperateException(MessageConstant.SONG_URL_ALTER_FAIL);
        }

    }

    /**
     * 管理端更新歌曲的图片
     * @param imgFile
     * @param id
     * @return
     */
    public Result updateSongImg(MultipartFile imgFile, int id) {
        String originalFilename = imgFile.getOriginalFilename();
        String newImgPath = PicPathConstant.SONG_PIC_PATH + originalFilename;

        boolean flag = lambdaUpdate().eq(Song::getId, id).set(Song::getPic, newImgPath).update();

        String s = minioService.uploadFile(MinioPicPathConstant.SONG_IMAGES_PATH, originalFilename, imgFile);
        if (s.equals("File uploaded successfully.") && flag) {
            return Result.success(MessageConstant.SONG_URL_ALTER_SUCCESS, newImgPath);
        } else {
            throw new MinioOperateException(MessageConstant.SONG_URL_ALTER_FAIL);
        }

    }

    /**
     * 管理端更新歌曲歌词
     * @param lrcFile
     * @param id
     * @return
     */
    public Result updateSongLrc(MultipartFile lrcFile, int id) {
        if (lrcFile == null) {
            throw new AdminOperateException(MessageConstant.ALTER_FAIL);
        }

        byte[] fileContent = new byte[0];
        boolean flag = false;
        try {
            fileContent = lrcFile.getBytes();
            String content = new String(fileContent, "GB2312"); // 把 fileContent 使用 GB2312 编码方式解码成字符串
            flag = lambdaUpdate().eq(Song::getId, id).set(Song::getLyric, content).update();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        if (flag) {
            return Result.success(MessageConstant.ALTER_SUCCESS);
        } else {
            throw new AdminOperateException(MessageConstant.ALTER_FAIL);
        }

    }

    /**
     * 删除歌曲，同时还要删除歌曲的评论、歌曲被收藏的记录、删除minio中存储的歌曲音频和图片
     * @param id
     * @return
     */
    @Transactional
    public Result deleteSong(int id) {
        Song song = songMapper.selectById(id);

        int flag = songMapper.deleteById(id);
        if (!(flag > 0)) {
            throw new MinioOperateException(MessageConstant.DELETE_FAIL +","+ MessageConstant.SONG_NOT_EXIST);
        }

        commentMapper.delete(new QueryWrapper<Comment>().eq("song_id", id)); // id是歌曲id

        collectMapper.delete(new QueryWrapper<Collect>().eq("song_id", id)); // id是歌曲id

        String urlPath = song.getUrl();
        if (urlPath != null && "song/".equals(urlPath.substring(0,5))) {
            String fileName = urlPath.substring(urlPath.lastIndexOf("/") + 1);
            minioService.deleteFile(MinioPicPathConstant.SONG_PATH, fileName);
        }

        String picPath = song.getPic();
        if (!picPath.equals(PicPathConstant.DEFAULT_SONG_PIC) && "minio/".equals(picPath.substring(0,6))) {
            String filename = picPath.substring(picPath.lastIndexOf("/") + 1);
            minioService.deleteFile(MinioPicPathConstant.SONG_IMAGES_PATH, filename);
        }

        return Result.success(MessageConstant.DELETE_SUCCESS);
    }

    /**
     * 根据歌曲id获取歌曲信息
     *
     * @param id
     * @return
     */
    public List<SongVO> getSongById(int id) {
        Song song = songMapper.selectById(id);
        SongVO songVO = BeanUtil.copyProperties(song, SongVO.class); // 用hutool包中的BeanUtil
        List<SongVO> songVOList = new ArrayList<>();
        songVOList.add(songVO);
        return songVOList;
    }

    /**
     * 根据歌手id获取歌曲
     * @param singerId
     * @return
     */
    @Cacheable(value = "singer", key = "#singerId")
    public List<SongVO> getSongBySingId(Integer singerId) {
        log.info("此次获取歌手：{} 的所有歌曲没有走缓存", singerId);
        List<Song> songList = lambdaQuery()
                .eq(Song::getSingerId, singerId) // 查询数据库中sing_id字段等于singId的记录
                .list();
        List<SongVO> songVOList = new ArrayList<>();
        for (Song song : songList) {
            SongVO songVO = BeanUtil.copyProperties(song, SongVO.class); // 把Song中的属性复制到SongVO中
            songVOList.add(songVO); // 把SongVO添加到SongVO集合中
        }
        return songVOList;
    }

    /**
     * 根据歌曲名和歌手名来进行模糊查询歌曲信息
     * @return
     */
    public Result<List<SongVO>> getSongLikeName(String name) {
        List<Song> songList = lambdaQuery()
                .like(name != null, Song::getName, name)
                .list();
        List<SongVO> songVOList = new ArrayList<>();
        for (Song song : songList) {
            SongVO songVO = BeanUtil.copyProperties(song, SongVO.class); // 把Song中的属性复制到SongVO中
            songVOList.add(songVO); // 把SongVO添加到SongVO集合中
        }
        return Result.success(songVOList);
    }
}
